/*
 * SalaDePersonas.cpp
 *
 *  Created on: 05/07/2014
 *      Author: migue
 */

#include "SalaDePersonas.h"
#include "../ipc/MemoriaCompartida.h"
#include <stdlib.h>
#include <stdio.h>
#include <syslog.h>

SalaDePersonas::SalaDePersonas(int numSala, int lugar) {
	//inicializo para eliminar errores del compilador
	_posCantPersonas = 0;
	_posReservas = 0;
	_posLugares = 0;
	_posEstadoBUS = 0;
	_numSala = 0;
	_lugar = (Tipos::LugarDeSala)0;
	_lugares = 0;

	perror("Metodo de Sala de personas obsoleto");
	exit(EXIT_FAILURE);
//
//	SALA sala;
//
//	_posCantPersonas = 0;
//	_posReservas = sizeof(sala.cantPersonas);
//	_posLugares = _posReservas + sizeof(sala.reservas);
//	_posEstadoBUS = _posLugares + sizeof(sala.personas);
//
//
//	_numSala = numSala;
//	_lugarSala = lugar;
//
//	char idIPC;
//
//	if (_lugarSala == LUGAR_SALA_ENTRADA) {
//		idIPC = ID_SHM_SALA_ENT(_numSala);
//	}
//	else if (_lugarSala == LUGAR_SALA_ZOO) {
//		idIPC = ID_SHM_SALA_ZOO(_numSala);
//	}
//	else {
//		perror("Error en la construccion de Sala de Personas, mal parametro del LUGAR de SALA");
//		exit(EXIT_FAILURE);
//	}
//
//	_lugares = new MemoriaCompartida(RUTA, idIPC, sizeof(SALA));

}

SalaDePersonas::SalaDePersonas(int numSala, Tipos::LugarDeSala lugar, bool crear) {
	SALA sala;

	_posCantPersonas = 0;
	_posReservas = sizeof(sala.cantPersonas);
	_posLugares = _posReservas + sizeof(sala.reservas);
	_posEstadoBUS = _posLugares + sizeof(sala.personas);

	_numSala = numSala;
	_lugar = lugar;

	char idIPC;

	if (_lugar == Tipos::LUGAR_ENTRADA) {
		idIPC = ID_SHM_SALA_ENT(_numSala);
	} else if (_lugar == Tipos::LUGAR_ZOO) {
		idIPC = ID_SHM_SALA_ZOO(_numSala);
	} else {
		perror(
				"Error en la construccion de Sala de Personas, mal parametro del LUGAR de SALA");
		exit(EXIT_FAILURE);
	}

	if (crear)
		_lugares = new MemoriaCompartida(RUTA, idIPC, sizeof(SALA));
	else
		_lugares = NULL;
}

SalaDePersonas::~SalaDePersonas() {
	if (_lugares != NULL) {
		delete _lugares;
	}
}

void SalaDePersonas::inicializar() {
	SALA sala;

	sala.cantPersonas = 0;
	sala.reservas = 0;
	sala.estadoBUS = Tipos::BUS_ACTIVO;

	for (int i = 0; i < CANTMAX; ++i)
		sala.personas[i] = 0;

	_lugares->escribir(0, (void*) &sala, sizeof(sala));
}

void SalaDePersonas::destruir() {
	if (_lugares != NULL) {
		_lugares->destruir();
		delete _lugares;
		_lugares = NULL;
	}
}

bool SalaDePersonas::hayPersonas() {
	int cantPersonas;

	_lugares->leer(_posCantPersonas, (void*) &cantPersonas, sizeof(int));

	return (cantPersonas > 0);
}

void SalaDePersonas::reservarLugar(int idPersona) {
	SALA sala;

	_lugares->leer(0, (void*) &sala, sizeof(sala));

	bool lugarReservado = false;
	int i = 0;

	for (; i < CANTMAX && lugarReservado == false; ++i) {
		if (sala.personas[i] == LUGAR_VACIO) {
			lugarReservado = true;
			sala.personas[i] = -idPersona; // valor negativo de id significa reserva de ese id
			sala.reservas++;
		}
	}

	_lugares->escribir(0, (void*) &sala, sizeof(sala));

	if (lugarReservado == false) {
		syslog(LOG_INFO,
				"No se logro Reservar lugar en la Sala con Persona con id: %i",
				idPersona);
		perror("No se logro reservar lugar en la Sala");
	}

}

void SalaDePersonas::colocarEnReserva(int idPersona) {
	SALA sala;

	_lugares->leer(0, (void*) &sala, sizeof(sala));

	bool colocado = false;

	for (int i = 0; i < CANTMAX && colocado == false; ++i) {

		if (sala.personas[i] == -idPersona) {
			colocado = true;
			sala.personas[i] = idPersona;
			sala.cantPersonas++;
		}
	}

	if (colocado == false) {
		syslog(LOG_INFO, "No se pudo colocar Persona id: %i en reserva",
				idPersona);
		perror("No se pudo colocar Persona en Reserva");
	} else {
		_lugares->escribir(0, (void*) &sala, sizeof(sala));
	}
}

int SalaDePersonas::verProximaPersona() {
	int proxId;

	SALA sala;

	_lugares->leer(0, (void*) &sala, sizeof(sala));

	bool hayProx = false;
	int i = 0;

	for (; i < CANTMAX && hayProx == false && sala.cantPersonas > 0; ++i) {
		if (sala.personas[i] > 0) {
			proxId = sala.personas[i];
			hayProx = true;
		}
	}

	if (hayProx == false) {
		return 0;
	} else {
		return proxId;
	}

}

void SalaDePersonas::sacarPersona(int idPersona) {
	SALA sala;

	_lugares->leer(0, (void*) &sala, sizeof(sala));

	bool encontrado = false;
	int i = 0;

	for (; i < CANTMAX && encontrado == false && sala.cantPersonas > 0; ++i) {
		if (sala.personas[i] == idPersona) {
			encontrado = true;
			sala.personas[i] = LUGAR_VACIO;

			sala.cantPersonas--;
			sala.reservas--;
		}
	}

	if (encontrado == false) {
		perror("No se encontro persona para sacar de la Sala");
	} else {
		_lugares->escribir(0, (void*) &sala, sizeof(sala));
	}

}

int SalaDePersonas::cantidadDePersonas() {
	int cantidad;

	_lugares->leer(_posCantPersonas, (void*) &cantidad, sizeof(int));

	return cantidad;
}

Tipos::EstadoBUS SalaDePersonas::estadoBUS() {
	Tipos::EstadoBUS estado;

	_lugares->leer(_posEstadoBUS, (void*) &estado, sizeof(estado));

	return estado;
}

bool SalaDePersonas::salaLlena() {
	SALA sala;
	_lugares->leer(0, (void*) &sala, sizeof(sala));

	return (CANTMAX == sala.reservas);
}

void SalaDePersonas::BUSsubiendoPersonas() {
	estadoBUS(Tipos::BUS_SUBIENDO_PERS);
}

void SalaDePersonas::BUSDespierto() {
	estadoBUS(Tipos::BUS_ACTIVO);
}

void SalaDePersonas::BUSDormido() {
	estadoBUS(Tipos::BUS_PARADO);
}

void SalaDePersonas::BUSbajandoPersonas() {
	estadoBUS(Tipos::BUS_BAJANDO_PERS);
}

void SalaDePersonas::estadoBUS(Tipos::EstadoBUS estado) {
	_lugares->escribir(_posEstadoBUS, (void*) &estado, sizeof(estado));
}

int SalaDePersonas::numeroDeSala() {
	return _numSala;
}

Tipos::LugarDeSala SalaDePersonas::lugar() {
	return _lugar;
}
